package gamagora.game.entity
{
	import Box2D.Dynamics.b2Body;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	
	import gamagora.game.resources.OSImages;
	import gamagora.game.utils.Utils;

	public class OSGround extends OSBox
	{
		public static const BOUNCE:String = "bounce";
		
		private static const TILE_WIDTH:uint = 20;
		private static const TILE_HEIGHT:uint = 20;
		private static const ERODED_TILE_WIDTH:uint = 20;
		private static const ERODED_TILE_HEIGHT:uint = 4;
		
		protected var _bounce:Boolean;
		protected var _enableWallJump:Boolean;
		protected var _widthInTiles:uint;
		protected var _heightInTiles:uint;
		protected var _grAngle:Number;
		
		//Erosion
		protected var _noErosionUp:Array;
		protected var _noErosionDown:Array;
		protected var _noErosionLeft:Array;
		protected var _noErosionRight:Array;
		
		public function OSGround(X:Number=0, Y:Number=0, w:Number = 0, h:Number = 0, grAngle:Number = 0, bounce:Boolean = false, enableWallJump:Boolean = true)
		{
			super(GROUND, X, Y, w, h);
			//super(GROUND, X, Y, w, h, w, h, null, true); //utile pour le débug
			_bounce = bounce;
			_enableWallJump = enableWallJump;
			_grAngle = grAngle;
			
			if(_bounce)
			{
				loadGraphic(OSImages.BOUNCE, true, false, 211, 90);
				addAnimation(BOUNCE, [0, 1, 2, 3, 4, 5, 6], 20, false);
				offset.y = 44;
				offset.x = 8;
			}
			else
			{
				makeGraphic(w, h, 0xff000000, true);
			}
			
			//Physique
			_bodyDef.type = b2Body.b2_staticBody;
			_bodyDef.angle = grAngle * (Math.PI / 180);
			_fixDef.friction = 0;
			_fixDef.density = 0;
			_fixDef.restitution = 0;
			
			//Erosion
			_widthInTiles = w / TILE_WIDTH;
			_heightInTiles = h / TILE_HEIGHT;
		}
		
		public function setBorders(left:Boolean, right:Boolean):void
		{
			if(_grAngle == -45)
			{
				if(left && right)
				{
					offset.x = -20;
					offset.y = 60;
					loadGraphic(OSImages.INCLINED_RIGHT_BOTH, false, false, 140, 140, true);
				}
				else
				{
					if(left)
					{
						offset.x = -20;
						offset.y = 60;
						loadGraphic(OSImages.INCLINED_RIGHT_DOWN, false, false, 140, 140, true);
					}
					else
					{
						if(right)
						{
							offset.x = -20;
							offset.y = 60;
							loadGraphic(OSImages.INCLINED_RIGHT_UP, false, false, 140, 140, true);
						}
					}
				}
			}
			else
			{
				if(_grAngle == 45)
				{
					if(left && right)
					{
						offset.x = -20;
						offset.y = 60;
						loadGraphic(OSImages.INCLINED_LEFT_BOTH, false, false, 140, 140, true);
					}
					else
					{
						if(left)
						{
							offset.x = -20;
							offset.y = 60;
							loadGraphic(OSImages.INCLINED_LEFT_DOWN, false, false, 140, 140, true);
						}
						else
						{
							if(right)
							{
								offset.x = -20;
								offset.y = 60;
								loadGraphic(OSImages.INCLINED_LEFT_UP, false, false, 140, 140, true);
							}
						}
					}
				}
			}
		}
		
		public override function update():void
		{
			for(var i:uint=0;i<_nbEntities;i++)
			{
				_entities[i].update();
			}
			
			x = (_body.GetPosition().x * RATIO) - _physicWidth / 2;
			y = (_body.GetPosition().y * RATIO) - _physicHeight / 2;
					
			if(_debugBox)
			{
				_debugBox.x = x;
				_debugBox.y = y;
				_debugBox.angle = _body.GetAngle() * (180 / Math.PI);
			}
		}
		
		public function erode():void
		{
			//Haut
			for(var i:uint=0;i<_widthInTiles;i++)
			{
				if(!isNotErodedUp(i))
				{
					var erodedBlock:BitmapData = Utils.getRandomErodedBorder();
					var start:uint = i * TILE_WIDTH;
					for(var j:uint=start;j < start + ERODED_TILE_WIDTH;j++)
					{
						for(var k:uint=0;k<ERODED_TILE_HEIGHT;k++)
						{
							_pixels.lock();
							_pixels.setPixel32(j, k, erodedBlock.getPixel32(j - start, k));
							_pixels.unlock();
						}
					}
				}
			}
			
			//Bas
			for(i=0;i<_widthInTiles;i++)
			{
				if(!isNotErodedDown(i + _widthInTiles * (_heightInTiles - 1)))
				{
					erodedBlock = Utils.getRandomErodedBorder();
					start = i * TILE_WIDTH;
					for(j=start;j < start + ERODED_TILE_WIDTH;j++)
					{
						for(k=0;k<ERODED_TILE_HEIGHT;k++)
						{
							_pixels.lock();
							_pixels.setPixel32(j, height  - k, erodedBlock.getPixel32(j - start, k));
							_pixels.unlock();
						}
					}
				}
			}
			
			//Gauche
			for(i=0;i<_heightInTiles;i++)
			{
				if(!isNotErodedLeft(i * _widthInTiles))
				{
					erodedBlock = Utils.getRandomErodedBorder();
					start = i * TILE_HEIGHT;
					for(j=0;j < ERODED_TILE_HEIGHT;j++)
					{
						for(k=start;k<start + ERODED_TILE_WIDTH;k++)
						{
							_pixels.lock();
							_pixels.setPixel32(j, k, erodedBlock.getPixel32(k - start, j));
							_pixels.unlock();
						}
					}
				}
			}
			
			//Droite
			for(i=0;i<_heightInTiles;i++)
			{
				if(!isNotErodedRight(i * _widthInTiles + (_widthInTiles - 1)))
				{
					erodedBlock = Utils.getRandomErodedBorder();
					start = i * TILE_HEIGHT;
					for(j=0;j < ERODED_TILE_HEIGHT;j++)
					{
						for(k=start;k<start + ERODED_TILE_WIDTH;k++)
						{
							_pixels.lock();
							_pixels.setPixel32(width - j, k, erodedBlock.getPixel32(k - start, j));
							_pixels.unlock();
						}
					}
				}
			}
			
			resetHelpers();
		}
		
		public function setNoErosionUp(noErosionUp:Array):void
		{
			_noErosionUp = noErosionUp;
		}
		
		public function setNoErosionDown(noErosionDown:Array):void
		{
			_noErosionDown = noErosionDown;
		}
		
		public function setNoErosionLeft(noErosionLeft:Array):void
		{
			_noErosionLeft = noErosionLeft;
		}
		
		public function setNoErosionRight(noErosionRight:Array):void
		{
			_noErosionRight = noErosionRight;
		}
		
		//Utils
		
		private function isNotErodedUp(index:uint):Boolean
		{
			return isNotEroded(index, _noErosionUp);
		}
		
		private function isNotErodedDown(index:uint):Boolean
		{
			return isNotEroded(index, _noErosionDown);
		}
		
		private function isNotErodedLeft(index:uint):Boolean
		{
			return isNotEroded(index, _noErosionLeft);
		}
		
		private function isNotErodedRight(index:uint):Boolean
		{
			return isNotEroded(index, _noErosionRight);
		}
		
		private function isNotEroded(index:uint, array:Array):Boolean
		{
			if(array != null)
			{
				var contain:Boolean = false;
				for(var i:uint=0;i<array.length;i++)
				{
					if(array[i] == index)
					{
						contain = true;
						break;
					}
				}
				return contain;
			}
			
			return false;
		}
		
		//Getters Setters
			
		public function get bounce():Boolean
		{
			return _bounce;
		}

		public function get enableWallJump():Boolean
		{
			return _enableWallJump;
		}

		public function get grAngle():Number
		{
			return _grAngle;
		}

	}
}
